package 反射.反射开始;

import 反射.Fs;

import java.lang.reflect.Constructor;
import java.util.Random;

public class 获取运行时类 {
    public static void main(String[] args) throws Exception {
//        newInstanceTest();

        for (int i = 0; i < 10; i++) {
            int num = new Random().nextInt(5);//0,1,2,3
            String classPath = "";
            switch (num) {
                case 0:
                    classPath = "java.util.Date";
                    break;
                case 1:
                    classPath = "java.lang.Object";
                    break;
                case 2:
                case 4:
                    classPath = "反射.Fs";
                    break;
                case 3:
                    classPath = "java.sql.Date";
                    break;
            }
            try {
                Object[] a =null;
                if(num==2){
                    a=new Object[2];
                    a[0]=int.class;
                    a[1]=5;
                }else if(num==3){
                    a=new Object[2];
                    a[0]=long.class;
                    a[1]=System.currentTimeMillis();
                }else if(num==4){
                    a=new Object[4];
                    a[0]=String.class;
                    a[1]=int.class;
                    a[2]="我指定的";
                    a[3]=5;
                }
                Object obj = getInstance(classPath,a);
                System.out.println(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public static Object getInstance(String classPath,Object ... objects) throws Exception {
        Class clazz =  Class.forName(classPath);//for Name  名副其实
        if(objects==null){
            return clazz.newInstance();//classPath这个类必须有空参构造器
        }
        int k=objects.length>>1;
        Class<?>[] classes1= new Class<?>[k];
        Object[] objects2= new Object[k];
        for (int i = 0; i < k; i++) {
            classes1[i]= (Class<?>) objects[i];
            objects2[i]= objects[k+i];
        }
        Constructor cons = clazz.getDeclaredConstructor(classes1);//Declared  加这个   可以获得私有的
        cons.setAccessible(true);//保证可访问   使私有的可访问
        return cons.newInstance(objects2);
    }

    private static void newInstanceTest() throws InstantiationException, IllegalAccessException {
        /**
         * newInstance():调用此方法，创建对应的运行时类的对象。
         *               内部调用了运行时类的空参的构造器。
         *
         * 要想此方法正常地创建运行时类的对象，要求：
         * 1.运行时类必须提供空参的构造器
         * 2.空参的构造器的访问权限得够。通常，设置为public。
         *
         * 在javabean中要求提供一个public的空参构造器。原因：
         * 1.便于通过反射，创建运行时类的对象
         * 2.便于子类继承此运行时类时，默认调用super()时，保证父类有此构造器
         */
        Class<Fs> fsClass = Fs.class;
        Fs fs = fsClass.newInstance();//相当于new Fs()
        System.out.println(fs);
    }
}
